/*
*********************************************************************************************************
*
*	模块名称 : TFT液晶显示器驱动模块
*	文件名称 : LCD_ST7789.c
*	版    本 : V1.0
*	说    明 : ST7789 显示器分辨率为 320 * 240,  尺寸比例4：3
*
*********************************************************************************************************
*/

#include "bsp.h"

#define COMPRESS  0

static void Init_7789V(void);
static void ST7789_SetDispWin(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth);
static void ST7789_SetCursor(uint16_t _usX, uint16_t _usY);

/*
*********************************************************************************************************
*	函 数 名: ST7789_InitHard
*	功能说明: 初始化LCD
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_InitHard(void)
{
    Init_7789V();	/* 初始化7789V屏硬件 */
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_OutModeConfig
*	功能说明: 数据IO输出配置
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_OutModeConfig(void)
{
    GPIO_InitType GPIO_InitStructure;
    GPIO_ConfigPinRemap(GPIO_RMP_SW_JTAG_SW_ENABLE, ENABLE);

    GPIO_InitStructure.Pin = GPIO_PIN_DATA_7789;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitPeripheral(GPIO_PORT_DATA_7789, &GPIO_InitStructure);
}
/*
*********************************************************************************************************
*	函 数 名: ST7789_InModeConfig
*	功能说明: 数据IO输入配置
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_InModeConfig(void)
{
    GPIO_InitType GPIO_InitStructure;

    GPIO_InitStructure.Pin = GPIO_PIN_DATA_7789;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_InitPeripheral(GPIO_PORT_DATA_7789, &GPIO_InitStructure);
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_SetDirection
*	功能说明: 设置显示方向。
*	形    参:  _ucDir : 显示方向
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_SetDirection(uint8_t _ucDir)
{
    /*
    	Memory Access Control (36h)
    	This command defines read/write scanning direction of the frame memory.

    	These 3 bits control the direction from the MPU to memory write/read.

    	Bit  Symbol  Name  Description
    	D7   MY  Row Address Order
    	D6   MX  Column Address Order
    	D5   MV  Row/Column Exchange
    	D4   ML  Vertical Refresh Order  LCD vertical refresh direction control. 、

    	D3   BGR RGB-BGR Order   Color selector switch control
    	     (0 = RGB color filter panel, 1 = BGR color filter panel )
    	D2   MH  Horizontal Refresh ORDER  LCD horizontal refreshing direction control.
    	D1   X   Reserved  Reserved
    	D0   X   Reserved  Reserved
    */
    ST7789_CMD(0x36);

    /*  0表示竖屏(排线在下), 1表示竖屏(排线在上), 2表示横屏 (排线在右边), 3表示横屏(排线在左边) */
    if (_ucDir == 0)
    {
        ST7789_DATA((0 << 7) | (0 << 6) | (0 << 5) | (0 << 3));	/* 竖屏(排线在下) */
        GusLcdHeight = LCD_HEIGHT;
        GusLcdWidth = LCD_WIDTH;
    }

    else if (_ucDir == 1)
    {
        ST7789_DATA((1 << 7) | (1 << 6) | (0 << 5) | (0 << 3));	/* 竖屏(排线在上) */
        GusLcdHeight = LCD_HEIGHT;
        GusLcdWidth = LCD_WIDTH;
    }

    else if (_ucDir == 2)
    {
        ST7789_DATA((0 << 7) | (1 << 6) | (1 << 5) | (0 << 3));	/* 横屏 (排线在右边) */
        GusLcdHeight = LCD_WIDTH;
        GusLcdWidth = LCD_HEIGHT;
    }

    else if (_ucDir == 3)
    {
        ST7789_DATA((1 << 7) | (0 << 6) | (1 << 5) | (0 << 3));	/* 横屏(排线在左边) */
        GusLcdHeight = LCD_WIDTH;
        GusLcdWidth = LCD_HEIGHT;
    }
}

/*
*********************************************************************************************************
*	函 数 名: Init_7789V
*	功能说明: 初始化ST7789V驱动器
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
static void Init_7789V(void)
{
    /* 初始化LCD，写LCD寄存器进行配置 */
 #if ISP_Screen==0
    /* 初始化LCD，写LCD寄存器进行配置 */
    ST7789_CMD(0x11); //Sleep out
//	bsp_Delay(120);              //Delay 120ms
    //------------------------------------ST7789S Frame Rate-----------------------------------------//
    //--------------------------------------Display Setting------------------------------------------//
    ST7789_CMD(0x36);
    ST7789_DATA(0x00);
    ST7789_CMD(0x3a);
    ST7789_DATA(0x55);
    //--------------------------------ST7789V Frame rate setting----------------------------------//
    ST7789_CMD(0xb2);
    ST7789_DATA(0x0c);
    ST7789_DATA(0x0c);
    ST7789_DATA(0x00);
    ST7789_DATA(0x33);
    ST7789_DATA(0x33);
    ST7789_CMD(0xb7);
    ST7789_DATA(0x72);
    //---------------------------------ST7789V Power setting--------------------------------------//
    ST7789_CMD(0xbb);
    ST7789_DATA(0x3D);
    ST7789_CMD(0xc0);
    ST7789_DATA(0x2c);
    ST7789_CMD(0xc2);
    ST7789_DATA(0x01);
    ST7789_CMD(0xc3);
    ST7789_DATA(0x19);
    ST7789_CMD(0xc4);
    ST7789_DATA(0x20);
    ST7789_CMD(0xc6);
    ST7789_DATA(0x0f);
    ST7789_CMD(0xd0);
    ST7789_DATA(0xa7);
    ST7789_DATA(0xa1);
    //--------------------------------ST7789V gamma setting---------------------------------------//
    ST7789_CMD(0xe0);
    ST7789_DATA(0xd0);
    ST7789_DATA(0x03);
    ST7789_DATA(0x09);
    ST7789_DATA(0x0e);
    ST7789_DATA(0x11);
    ST7789_DATA(0x3d);
    ST7789_DATA(0x47);
    ST7789_DATA(0x55);
    ST7789_DATA(0x53);
    ST7789_DATA(0x1a);
    ST7789_DATA(0x16);
    ST7789_DATA(0x14);
    ST7789_DATA(0x1f);
    ST7789_DATA(0x22);
    ST7789_CMD(0xe1);
    ST7789_DATA(0xd0);
    ST7789_DATA(0x02);
    ST7789_DATA(0x08);
    ST7789_DATA(0x0d);
    ST7789_DATA(0x12);
    ST7789_DATA(0x2c);
    ST7789_DATA(0x43);
    ST7789_DATA(0x55);
    ST7789_DATA(0x53);
    ST7789_DATA(0x1e);
    ST7789_DATA(0x1b);
    ST7789_DATA(0x19);
    ST7789_DATA(0x20);
    ST7789_DATA(0x22);
    ST7789_CMD(0x29);
	
	   

    LCD7789_RST_0;    
	LCD7789_RST_1; 

    delay_ms(120); 	
#endif
#if ISP_Screen==1
	ST7789_CMD( 0x11);     

	delay_ms(120);                

	ST7789_CMD( 0x36);     
	ST7789_DATA(0x00);   

	ST7789_CMD( 0x3A);     
	ST7789_DATA(0x05);     

	ST7789_CMD( 0xB2);     
	ST7789_DATA(0x0C);   
	ST7789_DATA(0x0C);   
	ST7789_DATA(0x00);   
	ST7789_DATA(0x33);   
	ST7789_DATA(0x33);  

	ST7789_CMD( 0x35);     
	ST7789_DATA(0x00);     

	ST7789_CMD( 0xB7);     
	ST7789_DATA(0x00);   

	ST7789_CMD( 0xBB);     
	ST7789_DATA(0x33);   

	ST7789_CMD( 0xC0);     
	ST7789_DATA(0x2C);   

	ST7789_CMD( 0xC2);     
	ST7789_DATA(0x01);   

	ST7789_CMD( 0xC3);     
	ST7789_DATA(0x23);   

	ST7789_CMD( 0xC4);     
	ST7789_DATA(0x20);    

	ST7789_CMD( 0xC6);     
	ST7789_DATA(0x0F);   

	ST7789_CMD( 0xD0);     
	ST7789_DATA(0xA4);   
	ST7789_DATA(0xA1);   

	ST7789_CMD( 0xD6);     
	ST7789_DATA(0xA1); 

	ST7789_CMD( 0xE0);
	ST7789_DATA(0xF0);
	ST7789_DATA(0x05);
	ST7789_DATA(0x09);
	ST7789_DATA(0x0E);
	ST7789_DATA(0x0C);
	ST7789_DATA(0x19);
	ST7789_DATA(0x21);
	ST7789_DATA(0x44);
	ST7789_DATA(0x32);
	ST7789_DATA(0x18);
	ST7789_DATA(0x10);
	ST7789_DATA(0x0F);
	ST7789_DATA(0x06);
	ST7789_DATA(0x10);

	ST7789_CMD( 0xE1);
	ST7789_DATA(0xF0);
	ST7789_DATA(0x00);
	ST7789_DATA(0x02);
	ST7789_DATA(0x04);
	ST7789_DATA(0x03);
	ST7789_DATA(0x00);
	ST7789_DATA(0x21);
	ST7789_DATA(0x43);
	ST7789_DATA(0x32);
	ST7789_DATA(0x3A);
	ST7789_DATA(0x12);
	ST7789_DATA(0x10);
	ST7789_DATA(0x03);
	ST7789_DATA(0x0B);

	ST7789_CMD( 0x21);  

	ST7789_CMD( 0x29);     

	ST7789_CMD( 0x2C); 

#endif 

    ST7789_SetDirection(0);	/* 竖屏(排线在下边) */
#if 1
    /* 设置显示窗口 */
    ST7789_SetDispWin(0, 0, GusLcdHeight, GusLcdWidth);
#endif
    LCD_Fill_Rect(0, 0, 320, 240, CL_BLACK);
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_WRIO
*	功能说明: ST7789写IO信息
*	形    参: _ucCmd : 命令代码
*	返 回 值: 无
*********************************************************************************************************
*/
static void ST7789_WRIO(uint8_t _ucCmd)
{
    GPIO_WriteLow(GPIO_PORT_DATA_7789, _ucCmd);
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_RDIO
*	功能说明: ST7789读IO信息
*	形    参: 无
*	返 回 值: _ucData : 读出的IO信息
*********************************************************************************************************
*/
static uint8_t ST7789_RDIO(void)
{
    return (GPIO_ReadInputData(GPIO_PORT_DATA_7789) & 0x00FF);
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_CMD
*	功能说明: 向LCD控制器芯片发送命令
*	形    参: _ucCmd : 命令代码
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_CMD(uint8_t _ucCmd)
{
    LCD7789_RS_0;   //写地址
    LCD7789_RD_1;
    ST7789_WRIO(_ucCmd);
    LCD7789_CS_0;
    LCD7789_WR_0;
    LCD7789_WR_1;
    LCD7789_CS_1;
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_DATA
*	功能说明: 向LCD控制器芯片发送参数(data)
*	形    参: _ucParam : 参数数据
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DATA(uint8_t _ucParam)
{
    LCD7789_RS_1;   //写数据
    LCD7789_RD_1;
    ST7789_WRIO(_ucParam);
    LCD7789_CS_0;
    LCD7789_WR_0;
    LCD7789_WR_1;
    LCD7789_CS_1;
}


/*
*********************************************************************************************************
*	函 数 名: ST7789_DATA16
*	功能说明: 向LCD控制器芯片发送参数(data)
*	形    参: _ucParam : 参数数据
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DATA16(uint16_t data)
{
    LCD7789_RS_1;   //写数据
    LCD7789_RD_1;
    ST7789_WRIO(data >> 8);
    LCD7789_CS_0;
    LCD7789_WR_0;
    LCD7789_WR_1;
    LCD7789_CS_1;
    LCD7789_RS_1;   //写数据
    LCD7789_RD_1;
    ST7789_WRIO(data);
    LCD7789_CS_0;
    LCD7789_WR_0;
    LCD7789_WR_1;
    LCD7789_CS_1;
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_ReadData
*	功能说明: 向LCD控制器芯片读取数据(data)
*	形    参: 无
*	返 回 值: _ucData : 读出的IO信息
*********************************************************************************************************
*/
static uint8_t ST7789_ReadData(void)
{
    uint8_t _ucData;

    ST7789_InModeConfig();

    LCD7789_RS_1;   //读数据
    LCD7789_CS_0;
    LCD7789_RD_0;
    _ucData = ST7789_RDIO();
    LCD7789_RD_1;
    LCD7789_CS_1;

    ST7789_OutModeConfig();

    return _ucData;
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_SetDispWin
*	功能说明: 设置显示窗口，进入窗口显示模式。TFT驱动芯片支持窗口显示模式，这是和一般的12864点阵LCD的最大区别。
*	形    参:
*		_usX : 水平坐标
*		_usY : 垂直坐标
*		_usHeight: 窗口高度
*		_usWidth : 窗口宽度
*	返 回 值: 无
*********************************************************************************************************
*/
static void ST7789_SetDispWin(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth)
{
    ST7789_CMD(0X2A); 		/* 设置X坐标 */
    ST7789_DATA(_usX >> 8);	/* 起始点 */
    ST7789_DATA(_usX);
    ST7789_DATA((_usX + _usWidth - 1) >> 8);	/* 结束点 */
    ST7789_DATA(_usX + _usWidth - 1);

    ST7789_CMD(0X2B); 				  /* 设置Y坐标*/
    ST7789_DATA(_usY >> 8);  		  /* 起始点 */
    ST7789_DATA(_usY);
    ST7789_DATA((_usY + _usHeight - 1) >> 8);		/* 结束点 */
    ST7789_DATA((_usY + _usHeight - 1));
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_SetCursor
*	功能说明: 设置光标位置
*	形    参:  _usX : X坐标; _usY: Y坐标
*	返 回 值: 无
*********************************************************************************************************
*/
static void ST7789_SetCursor(uint16_t _usX, uint16_t _usY)
{
    ST7789_CMD(0X2A); 		/* 设置X坐标 */
    ST7789_DATA(_usX >> 8);	/* 先高8位，然后低8位 */
    ST7789_DATA(_usX);		/* 设置起始点和结束点*/

    ST7789_CMD(0X2B); 		/* 设置Y坐标*/
    ST7789_DATA(_usY >> 8);
    ST7789_DATA(_usY);
}


/*
*********************************************************************************************************
*	函 数 名: ST7789_ReadID
*	功能说明: 读取LCD驱动芯片ID， 4个bit
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
uint32_t ST7789_ReadID(void)
{
    uint8_t buf[4];

    ST7789_CMD(0X04);
    buf[0] = ST7789_ReadData();
    buf[1] = ST7789_ReadData();
    buf[2] = ST7789_ReadData();
    buf[3] = ST7789_ReadData();

    return (buf[1] << 16) + (buf[2] << 8) + buf[3];
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_DispOn
*	功能说明: 打开显示
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DispOn(void)
{
	
#if LCD_BK_PWM
    LCD7789_BL_0;
    LCD_SetPwmBackLight(LcdBrightParameter_t.GucLcdBright);
#else
    LCD7789_BL_1;       //关闭背光
#endif
	
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_DispOff
*	功能说明: 关闭显示
*	形    参:  无
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DispOff(void)
{
#if LCD_BK_PWM
    LCD_SetPwmMiNBackLight(0); //关闭显示

#else
    LCD7789_BL_0;       //关闭背光
#endif
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_ClrScr
*	功能说明: 根据输入的颜色值清屏
*	形    参:  _usColor : 背景色
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_ClrScr(uint16_t _usColor)
{
    uint32_t i;
    uint32_t n;

    ST7789_SetDispWin(0, 0, GusLcdHeight, GusLcdWidth);
    ST7789_SetCursor(0x0000, 0x0000);

    ST7789_CMD(0x2C); 			/* 准备读写显存 */

#if 1		/* 优化代码执行速度 */
    n = (GusLcdHeight * GusLcdWidth) / 8;

    for (i = 0; i < n; i++)
    {
        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);
        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);
        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);
        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);

        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);
        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);
        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);
        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);
    }

#else
    n = GusLcdHeight * GusLcdWidth;

    for (i = 0; i < n; i++)
    {
        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);
    }

#endif

}

/*
*********************************************************************************************************
*	函 数 名: ST7789_PutPixel
*	功能说明: 画1个像素
*	形    参:
*			_usX,_usY : 像素坐标
*			_usColor  ：像素颜色
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_PutPixel(uint16_t _usX, uint16_t _usY, uint16_t _usColor)
{
    ST7789_SetCursor(_usX, _usY);	/* 设置光标位置 */

    /* 写显存 */
    ST7789_CMD(0x2C);
    ST7789_DATA(_usColor >> 8);
    ST7789_DATA(_usColor);
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_DrawLine
*	功能说明: 采用 Bresenham 算法，在2点间画一条直线。
*	形    参:
*			_usX1, _usY1 ：起始点坐标
*			_usX2, _usY2 ：终止点Y坐标
*			_usColor     ：颜色
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DrawLine(uint16_t _usX1 , uint16_t _usY1 , uint16_t _usX2 , uint16_t _usY2 , uint16_t _usColor)
{
    int32_t dx , dy ;
    int32_t tx , ty ;
    int32_t inc1 , inc2 ;
    int32_t d , iTag ;
    int32_t x , y ;

    /* 采用 Bresenham 算法，在2点间画一条直线 */

    ST7789_PutPixel(_usX1 , _usY1 , _usColor);

    /* 如果两点重合，结束后面的动作。*/
    if (_usX1 == _usX2 && _usY1 == _usY2)
    {
        return;
    }

    iTag = 0 ;

    /* dx = abs ( _usX2 - _usX1 ); */
    if (_usX2 >= _usX1)
    {
        dx = _usX2 - _usX1;
    }

    else
    {
        dx = _usX1 - _usX2;
    }

    /* dy = abs ( _usY2 - _usY1 ); */
    if (_usY2 >= _usY1)
    {
        dy = _usY2 - _usY1;
    }

    else
    {
        dy = _usY1 - _usY2;
    }

    if (dx < dy)     /*如果dy为计长方向，则交换纵横坐标。*/
    {
        uint16_t temp;

        iTag = 1 ;
        temp = _usX1;
        _usX1 = _usY1;
        _usY1 = temp;
        temp = _usX2;
        _usX2 = _usY2;
        _usY2 = temp;
        temp = dx;
        dx = dy;
        dy = temp;
    }

    tx = _usX2 > _usX1 ? 1 : -1 ;    /* 确定是增1还是减1 */
    ty = _usY2 > _usY1 ? 1 : -1 ;
    x = _usX1 ;
    y = _usY1 ;
    inc1 = 2 * dy ;
    inc2 = 2 * (dy - dx);
    d = inc1 - dx ;

    while (x != _usX2)       /* 循环画点 */
    {
        if (d < 0)
        {
            d += inc1 ;
        }

        else
        {
            y += ty ;
            d += inc2 ;
        }

        if (iTag)
        {
//			ST7789_PutPixel ( y-1 , x , _usColor) ;
            ST7789_PutPixel(y , x , _usColor) ;
        }

        else
        {
//			ST7789_PutPixel ( x-1 , y , _usColor) ;
            ST7789_PutPixel(x , y , _usColor) ;
        }

        x += tx ;
    }
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_DrawHLine
*	功能说明: 绘制一条水平线 （主要用于UCGUI的接口函数）
*	形    参:  _usX1    ：起始点X坐标
*			  _usY1    ：水平线的Y坐标
*			  _usX2    ：结束点X坐标
*			  _usColor : 颜色
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DrawHLine(uint16_t _usX1 , uint16_t _usY1 , uint16_t _usX2 , uint16_t _usColor)
{
    uint16_t i;

    ST7789_SetDispWin(_usX1, _usY1, 1, _usX2 - _usX1 + 1);

    ST7789_CMD(0x2C);

    /* 写显存 */
    for (i = 0; i < _usX2 - _usX1 + 1; i++)
    {
        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);
    }

}

/*
*********************************************************************************************************
*	函 数 名: LCD9341_DrawVLine
*	功能说明: 画垂直平线 用UCGUI的接口函数
*	形    参: X,Y的坐标和颜色
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DrawVLine(uint16_t _usX1 , uint16_t _usY1 , uint16_t _usY2 , uint16_t _usColor)
{
    uint16_t i;

    for (i = _usY1; i <= _usY2; i++)
    {
        ST7789_PutPixel(_usX1, i, _usColor);
    }
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_DrawHColorLine
*	功能说明: 绘制一条彩色水平线 （主要用于UCGUI的接口函数）
*	形    参:  _usX1    ：起始点X坐标
*			  _usY1    ：水平线的Y坐标
*			  _usWidth ：直线的宽度
*			  _pColor : 颜色缓冲区
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DrawHColorLine(uint16_t _usX1 , uint16_t _usY1, uint16_t _usWidth, const uint16_t *_pColor)
{
    uint16_t i;

    ST7789_SetDispWin(_usX1, _usY1, 1, _usWidth);

    ST7789_CMD(0x2C);

    /* 写显存 */
    for (i = 0; i < _usWidth; i++)
    {
        ST7789_DATA((*_pColor) >> 8);
        ST7789_DATA(*_pColor++);
    }
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_DrawHTransLine
*	功能说明: 绘制一条彩色透明的水平线 （主要用于UCGUI的接口函数）， 颜色值为0表示透明色
*	形    参:  _usX1    ：起始点X坐标
*			  _usY1    ：水平线的Y坐标
*			  _usWidth ：直线的宽度
*			  _pColor : 颜色缓冲区
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DrawHTransLine(uint16_t _usX1 , uint16_t _usY1, uint16_t _usWidth, const uint16_t *_pColor)
{
    uint16_t i, j;
    uint16_t Index;

    ST7789_SetCursor(_usX1, _usY1);

    /* 写显存 */
    ST7789_CMD(0x2C);

    for (i = 0, j = 0; i < _usWidth; i++, j++)
    {
        Index = *_pColor++;

        if (Index)
        {
            ST7789_DATA(Index >> 8);
            ST7789_DATA(Index);
        }

        else
        {
            ST7789_SetCursor(_usX1 + j, _usY1);
            ST7789_CMD(0x2C);
            ST7789_DATA(Index >> 8);
            ST7789_DATA(Index);
        }
    }
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_DrawRect
*	功能说明: 绘制水平放置的矩形。
*	形    参:
*			_usX,_usY：矩形左上角的坐标
*			_usHeight ：矩形的高度
*			_usWidth  ：矩形的宽度
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DrawRect(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth, uint16_t _usColor)
{
    /*
     ---------------->---
    |(_usX，_usY)        |
    V                    V  _usHeight
    |                    |
     ---------------->---
    	  _usWidth
    */

    ST7789_DrawLine(_usX, _usY, _usX + _usWidth - 1, _usY, _usColor);	/* 顶 */
    ST7789_DrawLine(_usX, _usY + _usHeight - 1, _usX + _usWidth - 1, _usY + _usHeight - 1, _usColor);	/* 底 */

    ST7789_DrawLine(_usX, _usY, _usX, _usY + _usHeight - 1, _usColor);	/* 左 */
    ST7789_DrawLine(_usX + _usWidth - 1, _usY, _usX + _usWidth - 1, _usY + _usHeight, _usColor);	/* 右 */
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_FillRect
*	功能说明: 填充矩形。
*	形    参:
*			_usX,_usY：矩形左上角的坐标
*			_usHeight ：矩形的高度
*			_usWidth  ：矩形的宽度
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_FillRect(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth, uint16_t _usColor)
{
    uint32_t i;

    /*
     ---------------->---
    |(_usX，_usY)        |
    V                    V  _usHeight
    |                    |
     ---------------->---
    	  _usWidth
    */

    ST7789_SetDispWin(_usX, _usY, _usHeight, _usWidth);

    ST7789_CMD(0x2C);

    for (i = 0; i < _usHeight * _usWidth; i++)
    {
        ST7789_DATA(_usColor >> 8);
        ST7789_DATA(_usColor);
    }
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_DrawCircle
*	功能说明: 绘制一个圆，笔宽为1个像素
*	形    参:
*			_usX,_usY  ：圆心的坐标
*			_usRadius  ：圆的半径
*	返 回 值: 无
*********************************************************************************************************
*/

void ST7789_DrawCircle(uint16_t _usX, uint16_t _usY, uint16_t _usRadius, uint16_t _usColor)
{
    int32_t  D;			/* Decision Variable */
    uint32_t  CurX;		/* 当前 X 值 */
    uint32_t  CurY;		/* 当前 Y 值 */

    D = 3 - (_usRadius << 1);
    CurX = 0;
    CurY = _usRadius;

    while (CurX <= CurY)
    {
        ST7789_PutPixel(_usX + CurX, _usY + CurY, _usColor);
        ST7789_PutPixel(_usX + CurX, _usY - CurY, _usColor);
        ST7789_PutPixel(_usX - CurX, _usY + CurY, _usColor);
        ST7789_PutPixel(_usX - CurX, _usY - CurY, _usColor);
        ST7789_PutPixel(_usX + CurY, _usY + CurX, _usColor);
        ST7789_PutPixel(_usX + CurY, _usY - CurX, _usColor);
        ST7789_PutPixel(_usX - CurY, _usY + CurX, _usColor);
        ST7789_PutPixel(_usX - CurY, _usY - CurX, _usColor);

        if (D < 0)
        {
            D += (CurX << 2) + 6;
        }

        else
        {
            D += ((CurX - CurY) << 2) + 10;
            CurY--;
        }

        CurX++;
    }
}
/*
*********************************************************************************************************
*	函 数 名: ST7789_DrawBMP
*	功能说明: 在LCD上显示一个BMP位图，位图点阵扫描次序：从左到右，从上到下
*	形    参:
*			_usX, _usY : 图片的坐标
*			_usHeight  ：图片高度
*			_usWidth   ：图片宽度
*			_ptr       ：图片点阵指针
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DrawBMP(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth, const uint16_t *_ptr)
{
    uint16_t pix = 0, num = 0;
    uint16_t i = 0, index = 0, m = 0;
    const uint16_t *p;

    /* 设置图片的位置和大小， 即设置显示窗口 */
    ST7789_SetDispWin(_usX, _usY, _usHeight, _usWidth);

    p = _ptr;
    ST7789_CMD(0x2C);

    for (index = 0; index < _usHeight * _usWidth;)
    {
        /* 压缩处理 */
        if ((*p == 0 || *p == 0xFFFF || *p == 0xF800 || *p == 0x07E0 || *p == 0XE73C) && ((*(p + 1) & 0xF000) == 0))
        {
            pix = *p;
            num = *(++p) & 0X0FFF;

            for (i = 0; i < num; i++)
            {
                ST7789_DATA(pix >> 8);
                ST7789_DATA(pix);
                index++;
            }

            p++;
        }

        else
        {
            ST7789_DATA((*p) >> 8);
            ST7789_DATA((*p++));
            index++;
        }

        m++;
    }
}

/*
*********************************************************************************************************
*	函 数 名: ST7789_DrawBMPNP
*	功能说明: 在LCD上显示一个BMP位图，位图点阵扫描次序：从左到右，从上到下(非压缩处理)
*	形    参:
*			_usX, _usY : 图片的坐标
*			_usHeight  ：图片高度
*			_usWidth   ：图片宽度
*			_ptr       ：图片点阵指针
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DrawBMPNP(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth, const uint16_t *_ptr)
{
    uint32_t index = 0;
    const uint16_t *p;

    /* 设置图片的位置和大小， 即设置显示窗口 */
    ST7789_SetDispWin(_usX, _usY, _usHeight, _usWidth);

    p = _ptr;
    ST7789_CMD(0x2C);

    for (index = 0; index < _usHeight * _usWidth;)
    {
        /* 不做压缩处理 */
        ST7789_DATA((*p) >> 8);
        ST7789_DATA((*p++));
        index++;
    }
}


/*
*********************************************************************************************************
*	函 数 名: ST7789_DrawRLEBMPNP
*	功能说明: 在LCD上显示一个被压缩的BMP位图，位图点阵扫描次序：从左到右，从上到下
*	形    参:
*			_usX, _usY : 图片的坐标
*			_usHeight  ：图片高度
*			_usWidth   ：图片宽度
*			ucpInput_Data       ：被压缩的图像数据
*			ulCompressed_Length ：被压缩的图像大小
*	返 回 值: 无
*********************************************************************************************************
*/
void ST7789_DrawRLEBMPNP(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth, const uint16_t ucpInput_Data[],uint16_t ulCompressed_Length)
{
	uint32_t i = 0;
    uint32_t j = 0;
    uint32_t ulOutput_Index = 0;
	uint16_t ucValue;
	uint16_t ucCount;

	
	
	uint16_t ucpOutput_Data[36000];
	
    while (i < ulCompressed_Length)
    {
        ucValue = ucpInput_Data[i++];
        ucCount = ucpInput_Data[i++];

        for (j = 0; j < ucCount; j++)
        {
            ucpOutput_Data[ulOutput_Index++] = ucValue;	
        }
    }


	ST7789_DrawBMPNP(_usX, _usY, _usHeight, _usWidth, ucpOutput_Data);


}
/*
*********************************************************************************************************
*	函 数 名: ST7789_DrawBMPDC
*	功能说明: 在LCD上显示一个压缩过的BMP位图，位图点阵扫描次序：从左到右，从上到下(非压缩处理)
*	形    参:
*			_usX, _usY : 图片的坐标
*			_usHeight  ：图片高度
*			_usWidth   ：图片宽度
*			_ptr       ：图片点阵指针
*	返 回 值: 无
*********************************************************************************************************
*/
void RLE_DeCompressu16(const uint16_t uspCompressed_Data[], uint32_t ulCompressed_Length, uint16_t uspOutput_Data[])
{
    uint32_t i = 0;
    uint32_t j = 0;
    uint32_t ulOutput_Index = 0;
	uint16_t usValue;
	uint16_t usCount;
	
    while (i < ulCompressed_Length)
    {
        usValue = uspCompressed_Data[i++];
        usCount = uspCompressed_Data[i++];

        for (j = 0; j < usCount; j++)
        {
            uspOutput_Data[ulOutput_Index++] = usValue;
        }
    }
}

void ST7789_DrawBMPDC(uint16_t _usX, uint16_t _usY, uint16_t _usHeight, uint16_t _usWidth, uint32_t ulNum, const uint16_t *_ptr)
{
	const uint16_t *p;
	uint32_t num2 = _usHeight * _usWidth;
	uint16_t usPic_Buffx[num2];

	/* 设置图片的位置和大小， 即设置显示窗口 */
	ST7789_SetDispWin(_usX, _usY, _usHeight, _usWidth);

	p = _ptr;
	RLE_DeCompressu16(p, ulNum, usPic_Buffx);
	
	ST7789_CMD(0x2C);
	for (num2 = 0; num2 < _usHeight * _usWidth;)
	{
		/* 不做压缩处理 */
		ST7789_DATA(usPic_Buffx[num2]>>8);
		ST7789_DATA(usPic_Buffx[num2]);
		num2++;
	}
}
/******************************************** END OF FILE *********************************************/
